package com.meatball.game.websocket

import com.alibaba.fastjson2.JSON
import com.meatball.game.data.*
import com.meatball.game.service.AiGameService
import com.meatball.game.service.RoomCacheService
import com.meatball.game.util.*
import org.slf4j.LoggerFactory
import org.springframework.data.redis.core.StringRedisTemplate
import org.springframework.web.socket.TextMessage
import org.springframework.web.socket.WebSocketSession
import java.util.concurrent.TimeUnit

/**
 * TODO 房间管理
 *
 * @author 张翔宇
 * @since 2024年3月7日
 */
class RoomManager(
        private val aiGameService: AiGameService,
        private val stringRedisTemplate: StringRedisTemplate,
        private val roomCacheService: RoomCacheService
) {
    companion object {
        private val logger = LoggerFactory.getLogger(RoomManager::class.java)
    }

    fun joinRoom(session: WebSocketSession): Room {
        // 解析url获取要加入的最大用户房间
        val maxUsers = (session.attributes["maxUsers"] as? String)?.toIntOrNull() ?: 0
        val id = session.attributes["id"].toString()
        val name = session.attributes["name"].toString()
        val avatar = session.attributes["avatar"].toString()

        // 找到一个可用的房间，或者创建一个新的
        val room = roomCacheService.getAllRoom().values.find { !it.isFull() && maxUsers == it.maxUsers }
                ?: Room(generateNoDashUUID(), maxUsers = maxUsers, isRealUser = if (maxUsers == 2) fiftyPercentChance() else false)
                        .also { roomCacheService.addRoom(it) }
        logger.info("当前房间信息：$room")
        // 将用户添加到房间
        room.users.add(RoomUser(
                id = id,
                name = name,
                avatar = avatar,
                session = session
        ))

        logger.info("当前房间编号：{}，房间人数：{}", room.id, room.users.size)

        // 如果房间满了则通知开始游戏
        if (room.isFull() ) {
            if (!room.isRealUser) {
                // 加入AI
                val aiUser = generatorRandomUser()
                room.users.add(RoomUser(
                        id = aiUser.id,
                        name = aiUser.name,
                        avatar = aiUser.avatar,
                        isAi = true
                ))
                roomCacheService.addRoom(room)
            }

            // 存入缓存
            stringRedisTemplate.opsForValue().set(ROOM + room.id, JSON.toJSONString(room.users), 5, TimeUnit.MINUTES)

            // 传递消息给AI后台
            val players = startGame(room)

            if (maxUsers < 4) {
                val message = JSON.toJSONString(ChatMessage(from = "system", text = "full", roomId = room.id))
                sendAllMessage(session, message)
            } else {
                // 分别发送角色信息
                room.users.forEach {user ->
                    players.forEach { player->
                        if (user.id == player.id) {
                            if (player.gameRole == "叛徒") {
                                player.aiName = players.find { it.isAi }?.name ?: ""
                            }
                            val message = JSON.toJSONString(ChatMessage(from = "system", text = "full", roomId = room.id, player = player))
                            logger.info("发送游戏开始消息(4人)：$message")
                            user.session?.sendMessage(TextMessage(message))
                        }
                    }
                }
            }
        }

        // 返回房间
        return room
    }

    fun leaveRoom(session: WebSocketSession) {
        // 找到用户所在的房间
        val id = session.attributes["id"].toString()
        val room = roomCacheService.getRoomByUserId(id) ?: return
        // 从房间中移除用户
        room.users.removeIf { user -> user.session == session }

        logger.info("用户离开房间：${room.id}，当前房间人数：${room.users.size.minus(1)}")

        // 如果房间为空，从列表中移除它
        if (room.users.size <= 1) {
            roomCacheService.removeRoom(room.id)
            // 游戏结束，删除key
            logger.info("房间解散，删除对应的房间：${room.id}")
        }
    }

    fun sendMessage(session: WebSocketSession, message: String) {
        // 找到用户所在的房间
        val id = session.attributes["id"].toString()
        val room = roomCacheService.getRoomByUserId(id) ?: return

        stringRedisTemplate.delete(COUNTDOWN + room.id)

        // 将消息发送给房间中的所有其他用户
        room.users.filter { it.session != session }.forEach {
            // 假设 send 是你定义的一个用来发送消息的函数
            it.session?.sendMessage(TextMessage(message))
        }
        if (room.isRealUser) return
        // 发送消息到AI端
        val msg = JSON.parseObject(message, ChatMessage::class.java)
        val params = ChatParams(
                playerId = msg.id,
                content = msg.text
        )
        aiGameService.chat(params, room)
    }

    private fun sendAllMessage(session: WebSocketSession, message: String) {
        // 找到用户所在的房间
        val id = session.attributes["id"].toString()
        val room = roomCacheService.getRoomByUserId(id) ?: return
        // 将消息发送给房间中的所有用户
        room.users.forEach {
            it.session?.sendMessage(TextMessage(message))
        }
    }

    /**
     * TODO 开始游戏
     *
     * @param room
     */
    private fun startGame(room: Room) : List<Player> {
        val players = mutableListOf<Player>()

        room.users.forEach {
            players.add(Player(
                    id = it.id,
                    name = it.name,
                    avatar = it.avatar,
                    isAi = it.isAi
            ))
        }

        val game = StartGame(
                id = room.id,
                gameType = "find_ai_${room.users.size}",
                players = players
        )
        logger.info("传递游戏开始参数：$game")
        return aiGameService.startGame(game)
    }
}